package at.jku.cp.mir.data;

import java.io.ByteArrayInputStream;
import java.io.File;
import java.io.FileNotFoundException;
import java.io.FileOutputStream;
import java.io.InputStream;
import java.io.OutputStream;
import java.util.Scanner;
import java.util.concurrent.TimeUnit;

import org.apache.commons.io.IOUtils;

import at.jku.cp.mir.LastFmCommunicator;

/**
 * This class fetches all needed data from Last.fm
 * @author clemens
 */
public abstract class DataFetcher
{

	private final File artistsFile;
	protected final LastFmCommunicator communicator;

	public DataFetcher(File artistFile)
	{
		super();
		this.artistsFile = artistFile;
		this.communicator = new LastFmCommunicator();
	}

	public void fetchData() throws FileNotFoundException
	{
		Scanner scanner = new Scanner(artistsFile);
		while (scanner.hasNextLine())
		{
			String line = scanner.nextLine();
			String artist = line;
			String lastFmArtist = line;

			// check if the lines contains the corrected, Last.fm artist
			//
			// one such line would look like "Brooks and Dunn --> Brooks & Dunn"
			// where "Brooks and Dunn" is the given artist name and
			// "Brooks & Dunn" is the artist's name on Last.fm
			if (line.contains(" --> "))
			{
				// split the string and re-assign the values of the artist and
				// the last.fm artist
				String[] splitted = line.split(" --> ");
				artist = splitted[0];
				lastFmArtist = splitted[1];
			}

			// delegate to implementing class
			boolean wait = fetchData(artist, lastFmArtist);

			// wait for a half second, so Last.fm won't complain about using
			// their API too often
			try
			{
				if (wait)
					Thread.sleep(500);
			} catch (InterruptedException e)
			{
				e.printStackTrace();
			}
		}
	}

	protected abstract boolean fetchData(String artist, String lastFmArtist);

	/**
	 * Get a file name conform String, which can be used as a file or directory
	 * name. For example "AC/DC" is not a valid filename, so this name would be
	 * translated to "AC_DC", which is valid for a file/dir name.
	 * @param name
	 * @return
	 */
	protected final String getFileConformName(String name)
	{
		return name.replace("/", "_");
	}

	/**
	 * Writes given data into a file.
	 * @param data
	 * @param file
	 */
	protected final void saveData(byte[] data, File file)
	{
		InputStream in = null;
		OutputStream out = null;
		try
		{
			in = new ByteArrayInputStream(data);
			out = new FileOutputStream(file);

			IOUtils.copy(in, out);
		} catch (Exception e)
		{
			e.printStackTrace();
		} finally
		{
			IOUtils.closeQuietly(in);
			IOUtils.closeQuietly(out);
		}
	}
}
